package com.wechat.admin.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wechat.admin.common.CommonConstants;
import com.wechat.admin.exception.BusinessException;
import com.wechat.admin.exception.ErrorCode;
import com.wechat.admin.mapper.GeweDockerTokenWithPortMapper;
import com.wechat.admin.mapper.TokenGroupLinkMapper;
import com.wechat.admin.mapper.UserMapper;
import com.wechat.admin.mapper.WeUserGroupMapper;
import com.wechat.admin.model.dto.UserInfoByGroupDto;
import com.wechat.admin.model.dto.UserInfoDto;
import com.wechat.admin.model.entity.GeweDockerTokenWithPort;
import com.wechat.admin.model.entity.TokenGroupLink;
import com.wechat.admin.model.entity.User;
import com.wechat.admin.model.entity.WeUserGroup;
import com.wechat.admin.model.request.AccessTokenRequest;
import com.wechat.admin.model.request.UserLoginRequest;
import com.wechat.admin.model.vo.UserInfoByGroupVo;
import com.wechat.admin.model.vo.UserLoginInfoVo;
import com.wechat.admin.service.UserService;
import com.wechat.admin.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author:sjb
 * @CreateTime:2024-12-14
 * @Description: 用户相关服务实现类
 * @Version：1.0
 */
@Slf4j
@Component
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private WeUserGroupMapper weUserGroupMapper;

    @Resource
    private TokenGroupLinkMapper tokenGroupLinkMapper;

    @Resource
    private GeweDockerTokenWithPortMapper geweDockerTokenWithPortMapper;


    @Override
    public long userRegister(String userAccount, String password, String checkPassword) {

        if (StrUtil.hasBlank(userAccount, checkPassword, checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        if (userAccount.length() < 4) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户昵称过短");
        }
        if (password.length() < 8 || checkPassword.length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码过短");
        }
        if (!password.equals(checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入的密码不一致");
        }

        // 检查是否重复
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userAccount", userAccount);
        Long count = this.baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号重复");
        }

        String encryptPassword = getEncryptPassword(password);
        User user = new User();
        user.setUserAccount(userAccount);
        user.setUserPassword(encryptPassword);
        user.setUserRole(CommonConstants.USER);
        boolean save = this.save(user);

        if (!save) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "注册失败，系统异常");
        }

        return user.getId();
    }

    @Override
    public String login(UserLoginRequest userLoginRequest) {
        String userName = removeAllSpaces(userLoginRequest.getUserName());
        String userPassword = userLoginRequest.getUserPassword();
        if (StrUtil.hasBlank(userName, userPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        if (userName.length() < 4) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号错误");
        }
        if (userPassword.length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码错误");
        }
        String encryptPassword = getEncryptPassword(userPassword);
        // 检查用户是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userAccount", userName)
                .eq("userPassword", encryptPassword);
        User user = this.baseMapper.selectOne(queryWrapper);
        if (user == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在");
        }
        return JwtUtil.generateToken(userName);
    }

    public String removeAllSpaces(String input) {
        return input != null ? input.replaceAll("\\s+", "") : null;
    }


    @Override
    public String getEncryptPassword(String userPassword) {
        final String salt = "weChat-manage";
        return DigestUtils.md5DigestAsHex((salt + userPassword).getBytes());
    }

    @Override
    public UserLoginInfoVo getCurrentLoginUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        log.info("authentication的信息为：{}", authentication);
        if (authentication == null || !authentication.isAuthenticated()) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "当前登录用户不存在");
        }
        // 获取用户信息
        return (UserLoginInfoVo) authentication.getPrincipal();
    }

    @Override
    public List<UserInfoDto> findUsersByGroupId(Integer groupId, int pageSize, int offset) {
        //ThrowUtils.throwIf(groupId == null, ErrorCode.PARAMS_ERROR);
        List<UserInfoDto> userInfoDtoS = userMapper.selectUsersByGroupId(groupId, pageSize, offset);
        if (userInfoDtoS == null || userInfoDtoS.isEmpty()) {
            return Collections.emptyList();
        }
        return userInfoDtoS;
    }

    @Override
    public List<UserInfoDto> findAllUser(int pageSize, int offset) {
        List<UserInfoDto> userInfoDtoS = userMapper.selectAllUsers(pageSize, offset);
        if (userInfoDtoS == null || userInfoDtoS.isEmpty()) {
            return Collections.emptyList();
        }
        return userInfoDtoS;
    }

    @Override
    public List<String> getAllUsers() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        List<User> userList = userMapper.selectList(queryWrapper);
        List<String> userNameList = userList.stream().map(User::getUserAccount).collect(Collectors.toList());
        if (!userNameList.isEmpty()) {
            return userNameList;
        }
        return Collections.emptyList();
    }

    @Override
    public UserInfoByGroupVo getAllUsersByGroup() {
        List<UserInfoByGroupDto> userInfoByGroupDtoS = userMapper.selectUsersWithGroup();
        log.info("查询出的信息为：{}", userInfoByGroupDtoS);
        return transformToViewObject(userInfoByGroupDtoS);
    }

    @Override
    public long updateTables() {
        return userMapper.testUpdateAllTable();
    }

    private UserInfoByGroupVo transformToViewObject(List<UserInfoByGroupDto> userInfoByGroupDtoS) {
        UserInfoByGroupVo viewVO = new UserInfoByGroupVo();
        // 存储按组分组的用户
        Map<String, List<UserInfoByGroupVo.UserInfoVo>> groupedUsersMap = new HashMap<>();
        // 存储没有分组的用户
        List<UserInfoByGroupVo.UserInfoVo> ungroupedUsers = new ArrayList<>();

        // 遍历所有用户信息
        for (UserInfoByGroupDto user : userInfoByGroupDtoS) {
            UserInfoByGroupVo.UserInfoVo userInfoVo = new UserInfoByGroupVo.UserInfoVo();
            userInfoVo.setUserName(user.getUserAccount());
            userInfoVo.setCreateTime(user.getCreateTime());
            userInfoVo.setUserRole(user.getUserRole());
            userInfoVo.setGroupName(user.getGroupName());

            // 判断是否有分组
            if (user.getUserGroup() != null) {
                groupedUsersMap.computeIfAbsent(user.getGroupName(), k -> new ArrayList<>()).add(userInfoVo);
            } else {
                // 没有分组的用户
                userInfoVo.setGroupName("");
                ungroupedUsers.add(userInfoVo);
            }
        }

        // 将按组分组的用户数据转换为视图对象
        List<UserInfoByGroupVo.GroupedUserInfo> groupedUserInfoList = groupedUsersMap.entrySet().stream()
                .map(entry -> {
                    UserInfoByGroupVo.GroupedUserInfo groupedUserInfo = new UserInfoByGroupVo.GroupedUserInfo();
                    groupedUserInfo.setGroupName(entry.getKey());
                    groupedUserInfo.setUsers(entry.getValue());
                    return groupedUserInfo;
                })
                .collect(Collectors.toList());

        // 设置视图对象中的分组用户和未分组用户
        viewVO.setGroupedUsers(groupedUserInfoList);
        viewVO.setUngroupedUsers(ungroupedUsers);

        return viewVO;
    }

    /**
     * 分配token给用户到组
     *
     * @param accessTokenRequest
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean assignmentTokenToUser(AccessTokenRequest accessTokenRequest) {
        String token = accessTokenRequest.getToken();
        String deviceName = accessTokenRequest.getDeviceName();
        String groupName = accessTokenRequest.getGroupName();

        QueryWrapper<WeUserGroup> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("groupname", groupName);
        WeUserGroup weUserGroup = weUserGroupMapper.selectOne(queryWrapper);
        if (weUserGroup == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "所分配组不存在,请确认信息");
        }

        Integer id = weUserGroup.getId();
        // 保存组和token的关联表
        TokenGroupLink tokenGroupLink = new TokenGroupLink();
        tokenGroupLink.setToken(token);
        tokenGroupLink.setDevicename(deviceName);
        tokenGroupLink.setGroupid(id);
        tokenGroupLink.setUserName(accessTokenRequest.getUserName());
        int insert = tokenGroupLinkMapper.insert(tokenGroupLink);

        QueryWrapper<GeweDockerTokenWithPort> geweDockerTokenWithPortQueryWrapper = new QueryWrapper<>();
        geweDockerTokenWithPortQueryWrapper.eq("device_name", deviceName);
        GeweDockerTokenWithPort geweDockerTokenWithPort =
                geweDockerTokenWithPortMapper.selectOne(geweDockerTokenWithPortQueryWrapper);

        if (geweDockerTokenWithPort != null) {
            LambdaUpdateWrapper<GeweDockerTokenWithPort> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(GeweDockerTokenWithPort::getDevice_name, deviceName);
            geweDockerTokenWithPort.setIsused(CommonConstants.TOKEN_STATUS.ASSIGNED);
            geweDockerTokenWithPortMapper.update(geweDockerTokenWithPort, updateWrapper);
        }
        return insert > 0;
    }


}
